import java.util.*;
import java.io.*;

public class Forward extends MarkovModelAlgo {

  double[][] f;

  protected int L; 

  public Forward(HMM hmm, Object x[]) {
    super(hmm, x);
    L = x.length;
    f = new double[L+1][hmm.nstate];
    f[0][0] = 0;
    for (int k=1; k<hmm.nstate; k++) f[0][k] = Double.NEGATIVE_INFINITY;
    for (int i=1; i<=L; i++) f[i][0] = Double.NEGATIVE_INFINITY;
    for (int i=1; i<=L; i++) for (int ell=1; ell<hmm.nstate; ell++) {
        double sum = Double.NEGATIVE_INFINITY;
        for (int k=0; k < hmm.nstate; k++) sum = logplus(sum, f[i-1][k] + hmm.loga[k][ell]);
        f[i][ell] = hmm.loge[ell][hmm.getSym(x[i-1])] + sum;  
      }    
  }

  public Forward ( MM mm , Object[] x ) {
	super(mm, x);
        L = x.length;
        f = new double[L+1][1];
	f[0][0] = Double.NEGATIVE_INFINITY;
	f[1][0] = mm.loge[0][mm.getSym(x[0])];
	for (int i=1; i < x.length; i++) f[i+1][0] = logplus(f[i][0] , mm.loge[mm.getSym(x[i-1])][mm.getSym(x[i])]);
  }

  double logprob() {
    double sum = Double.NEGATIVE_INFINITY;
    int nstate = ( mm instanceof HMM ) ? ((HMM)mm).nstate : 1;
    for (int k=0; k<nstate; k++) sum = logplus(sum, f[L][k]);
    return sum;
  }

  public void print(PrintStream out) {
    int nstate = ( mm instanceof HMM ) ? ((HMM)mm).nstate : 1;
    for (int j=0; j<nstate; j++) {
      for (int i=0; i<f.length; i++) out.print(MarkovModel.fmtlog(f[i][j]));
      out.println();
    }
  }

}

